#include "mpLog.h"
#include "mpFileUtils.h"
#include "mpLruCache.h"
#include "mpLruCacheTests.h"


class Person {
public:
    int id;
    int age;
};



mpLruCacheTests::mpLruCacheTests()
{
}

void mpLruCacheTests::initTestCase(){}
void mpLruCacheTests::cleanupTestCase(){}



void mpLruCacheTests::case_lruCache(){
#ifdef TEST_STRATEGY_COMPLETED

    const size_t test_size = 50;
    const size_t test_put_record = 100;

    MP::LruCache<size_t, size_t> testcache1(test_size);
    for (size_t i = 1; i <= test_put_record; ++i) {
        testcache1.Put(i, i);
        std::string msgExist = "mpLruCache exist " + std::to_string(i);
        std::string msgGet = "mpLruCache get " + std::to_string(i);
        std::string msgSize = "mpLruCache size " + std::to_string(i);

        QVERIFY2(testcache1.Exist(i),msgExist.c_str());
        QVERIFY2(testcache1.Get(i)== i,msgGet.c_str());

        if (i <= test_size) {
            QVERIFY2(testcache1.Size() == i,msgSize.c_str());
            for (size_t j = 1; j <= i; ++j) {
                std::string msgExistJ = "mpLruCache exist " + std::to_string(j);
                std::string msgGetJ = "mpLruCache get " + std::to_string(j);
                QVERIFY2(testcache1.Exist(j), msgExistJ.c_str());
                QVERIFY2(testcache1.Get(j)== j,msgGetJ.c_str());
            }
        } else {

            QVERIFY2(testcache1.Size() == test_size,"mpLruCache size = 50");

            for (size_t j = 1; j <= i - test_size; ++j) {

                std::string msgNotExistJ = "mpLruCache not exist " + std::to_string(j);
                QVERIFY2(!testcache1.Exist(j), msgNotExistJ.c_str());
            }
        }
    }

    MP::LruCache<size_t, size_t> testcache2(test_size);
    for (size_t i = 1; i <= test_put_record; ++i) {
        testcache2.Put(1, i);
        QVERIFY2(testcache2.Size() == 1,"mpLruCache size always = 1");
        QVERIFY2(testcache2.Get(1)== i,"mpLruCache get value always = 1");
    }

#endif
}

void mpLruCacheTests::case_lruObjCache(){
#ifdef TEST_STRATEGY_COMPLETED

    MP::LruObjCache<int, Person> personCache(5, [](int id, Person* person) {
        //当对象被顶出去（删除）的时候会执行到这里
        printf("person:%d deleted\n", id);
        delete person;
    });

    for (int i = 0; i < 10; i++) {
        auto p = new Person;
        p->id = i;
        p->age = 10 + i;
        personCache.put(p->id, p);
    }

    /*
        0,1,2,3,4 应该已经被顶出去了
        5,6,7,8,9 应该在其中
        */

    auto obj = personCache.get(0);
    QVERIFY2(obj == nullptr,"mpLruObjCache id=0 is not exist . (false :0,1,2,3,4 true : 9,8,7,6,5)");

    obj = personCache.get(3);
    QVERIFY2(obj == nullptr,"mpLruObjCache id=3 is not exist . (false :0,1,2,3,4 true : 9,8,7,6,5)");

    /*
        5被引用了一次，下次6会在5之前被顶出去
        */

    obj = personCache.get(5);
    QVERIFY2(obj != nullptr,"mpLruObjCache id=5 exist . (false :0,1,2,3,4 true : 5,9,8,7,6)");

    auto p = new Person;
    p->id = 100;
    p->age = 200;

    personCache.put(p->id, p);

    obj = personCache.get(6);
    QVERIFY2(obj == nullptr,"mpLruObjCache id=6 is not exist. (false :0,1,2,3,4,5,6 true : 100,5,9,8,7)");

#endif
}
